package com.idealighter.game.games.errenniuniu.manager;

import com.alibaba.fastjson.TypeReference;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.core.common.Game;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsType;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsTypeComparator;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsTypeGetter;
import com.idealighter.game.games.errenniuniu.struct.ErRenNiuNiuSeat;
import com.idealighter.game.games.errenniuniu.struct.ErRenNiuNiuTable;
import com.idealighter.game.prizepool.manager.PlayerPrizePoolMgrScript;
import com.idealighter.game.prizepool.manager.RoomPrizePoolMgrScript;
import com.idealighter.game.prizepool.struct.control.ErRenNiuNiuControl;
import com.idealighter.game.prizepool.struct.player.PlayerPrizePool;
import com.idealighter.game.prizepool.struct.room.ControlStrategy;
import com.idealighter.game.prizepool.struct.room.RoomPrizePool;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 牛牛控制 .
 * 
 * @date 2015年10月17日 下午7:41:31
 *
 */
@Singleton
public class ErRenNiuNiuControlScript {

  private static final TypeReference<ErRenNiuNiuControl> ERREN_NIUNIU_CONTROL_TYPE =
      new TypeReference<ErRenNiuNiuControl>() {};

  @Inject
  private ErRenNiuNiuMgr niuniuMgr;

  @Inject
  private PlayerPrizePoolMgrScript playerPrizePoolMgr;
  @Inject
  private RoomPrizePoolMgrScript roomPrizePoolMgr;

  /**
   * 控制玩家发牌,玩家和机器人玩才控制 .
   * 
   * @param table .
   */
  public void controlDealCards(ErRenNiuNiuTable table) {
    // 庄家
    ErRenNiuNiuSeat dealer;
    // 闲家
    ErRenNiuNiuSeat seat;
    if (table.seat1.dealer) {
      dealer = table.seat1;
      seat = table.seat2;
    } else {
      dealer = table.seat2;
      seat = table.seat1;
    }

    /*
     * 玩家和机器人玩且有个人奖池 .
     */
    if (!seat.isRobot() && dealer.isRobot()) {
      // 闲家个人奖池
      PlayerPrizePool seatPrizePool =
          playerPrizePoolMgr.prizePool(seat.getPlayerId(), Game.ERREN_NIUNIU);
      if (seatPrizePool != null && seatPrizePool.getPrize().get() != 0) {
        playerPrizePoolControlDealCards(seat, seatPrizePool);
        return;
      }
    } else if (seat.isRobot() && !dealer.isRobot()) {
      // 庄家个人奖池
      PlayerPrizePool dealerPrizePool =
          playerPrizePoolMgr.prizePool(dealer.getPlayerId(), Game.ERREN_NIUNIU);
      if (dealerPrizePool != null && dealerPrizePool.getPrize().get() != 0) {
        playerPrizePoolControlDealCards(dealer, dealerPrizePool);
        return;
      }
    }

    /*
     * 玩家和机器人玩被库存奖池控制 .
     */
    if (!seat.isRobot() && dealer.isRobot()) { // 控制闲家
      RoomPrizePool seatRoomPrizePool =
          roomPrizePoolMgr.roomPrizePool(seat.getPlayerId(), Game.ERREN_NIUNIU, table.room.getId());
      if (seatRoomPrizePool != null) {
        roomPrizePoolControlDealCards(seat, seatRoomPrizePool);
        return;
      }

    } else if (seat.isRobot() && !dealer.isRobot()) { // 控制庄家
      RoomPrizePool dealerRoomPrizePool = roomPrizePoolMgr.roomPrizePool(dealer.getPlayerId(),
          Game.ERREN_NIUNIU, table.room.getId());
      if (dealerRoomPrizePool != null) {
        roomPrizePoolControlDealCards(dealer, dealerRoomPrizePool);
        return;
      }
    }

    // 正常发牌
    normalDealCards(table);
  }

  /**
   * 控制房间奖池 .
   * 
   * @param seat 座位信息.
   * @param prizePool .
   */
  private void roomPrizePoolControlDealCards(ErRenNiuNiuSeat seat, RoomPrizePool prizePool) {
    // 房间奖池控制策略
    ControlStrategy strategy = prizePool.abledControlStrategy();
    ErRenNiuNiuTable table = seat.table;

    List<NiuNiuCard> seatCards = null;
    List<NiuNiuCard> otherCards = null;
    NiuNiuCardsType seatCardsType = null;
    NiuNiuCardsType otherCardsType = null;
    // 玩家下注
    long betedchips = seat.dealer ? seat.otherSeat().betedchips : seat.betedchips;

    if (strategy != null) { // 有控制策略,直到符合结果为止
      // 牛牛控制
      ErRenNiuNiuControl control = strategy.control(ERREN_NIUNIU_CONTROL_TYPE);
      boolean res = RandCodeUtil.random(control.getLoseRatio() + control.getWinRatio()) >= control
          .getLoseRatio();

      for (;;) {
        List<NiuNiuCard> cardsTmp = new ArrayList<>(table.cards);
        seatCards = RandCodeUtil.randomList(cardsTmp, 5);
        cardsTmp.removeAll(seatCards);
        otherCards = RandCodeUtil.randomList(cardsTmp, 5);

        seatCardsType = NiuNiuCardsTypeGetter.getCardsType(seatCards, new ArrayList<>());
        otherCardsType = NiuNiuCardsTypeGetter.getCardsType(otherCards, new ArrayList<>());

        if (res == NiuNiuCardsTypeComparator.compare(seatCards, seatCardsType, otherCards,
            otherCardsType)) {
          break;
        } else {
          continue;
        }
      }
    } else {
      List<NiuNiuCard> cardsTmp = new ArrayList<>(table.cards);
      seatCards = RandCodeUtil.randomList(cardsTmp, 5);
      cardsTmp.removeAll(seatCards);
      otherCards = RandCodeUtil.randomList(cardsTmp, 5);

      seatCardsType = NiuNiuCardsTypeGetter.getCardsType(seatCards, new ArrayList<>());
      otherCardsType = NiuNiuCardsTypeGetter.getCardsType(otherCards, new ArrayList<>());
    }

    boolean win =
        NiuNiuCardsTypeComparator.compare(seatCards, seatCardsType, otherCards, otherCardsType);
    long prize = prizePool.getPrize().get();
    long totalGold = niuniuMgr.convertGold(table.room.getId().intValue(),
        win ? seatCardsType.multiple * betedchips : -otherCardsType.multiple * betedchips);
    prize -= totalGold;
    prizePool.getPrize().getAndSet(prize);
    // 发牌
    niuniuMgr.doDealCards(table, seat, seatCards, seat.otherSeat(), otherCards);
  }

  /**
   * 控制玩家奖池 .
   * 
   * @param seat 座位信息.
   * @param prizePool .
   */
  private void playerPrizePoolControlDealCards(ErRenNiuNiuSeat seat, PlayerPrizePool prizePool) {
    // 玩家下注
    long betedchips = seat.dealer ? seat.otherSeat().betedchips : seat.betedchips;
    ErRenNiuNiuTable table = seat.table;

    // 牛牛控制
    ErRenNiuNiuControl control = prizePool.control(ERREN_NIUNIU_CONTROL_TYPE);
    boolean win = RandCodeUtil.random(control.getLoseRatio() + control.getWinRatio()) >= control
        .getLoseRatio();

    List<NiuNiuCard> seatCards = null;
    List<NiuNiuCard> otherCards = null;
    NiuNiuCardsType seatCardsType = null;
    NiuNiuCardsType otherCardsType = null;

    for (;;) {
      List<NiuNiuCard> cardsTmp = new ArrayList<>(table.cards);
      seatCards = RandCodeUtil.randomList(cardsTmp, 5);
      cardsTmp.removeAll(seatCards);
      otherCards = RandCodeUtil.randomList(cardsTmp, 5);

      seatCardsType = NiuNiuCardsTypeGetter.getCardsType(seatCards, new ArrayList<>());
      otherCardsType = NiuNiuCardsTypeGetter.getCardsType(otherCards, new ArrayList<>());

      boolean res =
          NiuNiuCardsTypeComparator.compare(seatCards, seatCardsType, otherCards, otherCardsType);

      if (res == win) {
        break;
      } else {
        continue;
      }
    }

    /*
     * 奖池为：60w,却赢了100w，则奖池达到要求变为0 . 奖池为：-60w,却输了100w，则奖池达到要求变为0
     */
    long prize = prizePool.getPrize().get();
    long totalGold = niuniuMgr.convertGold(table.room.getId().intValue(),
        win ? seatCardsType.multiple * betedchips : -otherCardsType.multiple * betedchips);

    if (prize > 0) {
      prize = prize - totalGold;
      prize = prize < 0 ? 0 : prize;
    } else if (prize < 0) {
      prize = prize - totalGold;
      prize = prize > 0 ? 0 : prize;
    }

    prizePool.getPrize().getAndSet(prize);
    niuniuMgr.doDealCards(table, seat, seatCards, seat.otherSeat(), otherCards);
  }

  /**
   * 正常发牌 .
   * 
   * @param table .
   */
  private void normalDealCards(ErRenNiuNiuTable table) {
    List<NiuNiuCard> cards = table.cards;
    int cardIndex = 0;

    List<NiuNiuCard> seat1Cards =
        cards.subList(cardIndex, cardIndex += ErRenNiuNiuMgr.PLAYER_CARDS);
    List<NiuNiuCard> seat2Cards =
        cards.subList(cardIndex, cardIndex += ErRenNiuNiuMgr.PLAYER_CARDS);
    // 发牌
    niuniuMgr.doDealCards(table, table.seat1, seat1Cards, table.seat2, seat2Cards);
  }

}
